﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using server.DataBase;
using server.Communication.Messages;
using server.log;
using System.Net;

namespace client
{
    public class ClientMessageHandler
    {
        private TcpClient client;
        private NetworkStream stream;
        private IFormatter formatter;
        private Data data;
        private bool connected;


        private Menu_Control Controller;
        private bool firstRun;
        private bool tryConnect;

        private Page Lastpage;//added by edi

        public ClientMessageHandler(TcpClient client)
        {

            this.client = client;
            this.formatter = new BinaryFormatter();
            this.stream = null;
            this.data = new Data();
            data.initData();
            this.connected = false;
            this.Controller = new Menu_Control();
            this.firstRun = true;
            this.tryConnect = false;
        }

        public void proccessMsg(Message msg, NetworkStream strm)
        {
            this.stream = strm;

            string type = msg.GetType();
            switch (type)
            {
                case "ClientAccepted":
                    this.Controller.LevelUP();//updateds conroller #######;
                    Console.WriteLine("Entered Forum");
                    enterForum();
                    break;

                case "ConnectResult":             //when we get this message - is there another option of faliure?
                   
                    if (((ConnectResult)msg).succ)
                    {

                        if (this.tryConnect == false)
                        {
                            send(new View(0), this.stream);
                            connected = true;

                        }else
                            if (this.tryConnect == true)
                            {
                                this.tryConnect = false;

                                if (this.firstRun == true)
                                {
                                    send(new View(0), this.stream);
                                    connected = true;
                                    this.firstRun = false;
                                }
                                else
                                {
                                    this.viewPage(this.Lastpage);
                                }

                            }
     
                    }
                    else
                    {
                        Console.WriteLine("Connection failed");

                        if (this.tryConnect == true)
                        {
                            this.tryConnect = false;

                            if (this.firstRun == true)
                                this.enterForum();
                            else
                            {
                                this.viewPage(this.Lastpage);
                            }

                        }
                    }
                    break;

                case "Page":
                    viewPage((Page)msg);
                    break;
                case "RegisterResult": ///what is RegisterResult? -- need succ
                    //Console.WriteLine(((RegisterResult)msg).succ);
                    if (((RegisterResult)msg).succ==true)
                    {

                        Console.WriteLine("Register Success");
                        if (this.firstRun == false)
                            this.viewPage(this.Lastpage);
                        else if (this.firstRun == true)
                            {
                                this.enterForum();
                            }
                    }
                    else
                    {
                        
                        Console.WriteLine("Register fail");
                      //  this.viewPage(this.Lastpage);
                    }
                   //HERE WILL BE ADDED THE FUNCTION TO PROCCESS THE MESSAGE RESULTS
                    break;

                case "PermitionDenied":
                    Console.WriteLine(" PREMETION DENIED");
                    this.viewPage(this.Lastpage);

                    //HERE WILL BE ADDED THE function for return to the screen you was on
                    break;
                case "Disconnect": ///from server or Disconnect as a member? perm 0    
                    connected = false;
                    break;
                case "HelpResult":
                    ShowHelp((HelpResult)msg);
                    break;
                default:
                    Console.WriteLine("Illegal message type " + type);
                    break;
            }
        }


        private void ShowHelp(HelpResult res)
        {
            Console.WriteLine("\n");
         
            Console.WriteLine(res.ToString());
            string choice = Console.ReadLine();
            ChoiseSwitch(choice, this.Lastpage);
        }




        private void viewPage(Page p)
        {
            Console.WriteLine("");
            this.Lastpage = p; //saves the last page we got

            Console.WriteLine(p.page.ToString());
        
 
            /* ---stack overflow problem-- fixed  -- change in page---> return page.subs.Count;*/
            if (p.lengh() > 0)
            {
                Console.WriteLine("To choose page insert a number from 1 to {0}", p.lengh());
            }


            string choice = Console.ReadLine();
            ChoiseSwitch(choice, p);
         
        }

        private void ChoiseSwitch(string choice,Page p)
        {
            switch (choice)
            {
                case "Post Thread":
                    //send(new CreateThread("edd", "edd"), this.stream);
                    Enter_Thread();
                    break;
                case "Post Item": //will work for now only if we in the lowest phase
                    //send(new CreatePost(" New Song", "   I LOVE BGU"), this.stream);
                    this.Enter_newPost();
                  // this.viewPage(this.Lastpage);
                   break;
                case "Back":
                  //  if (this.Controller.getPosition()!=1)
                  //  this.Controller.LevelDown();
                   send(new Back(),this.stream);  
                   break;
                case "Help":
                    send(new Help(), this.stream);
                    break;

                case "Register":
                    register();
                    break;

                case "Connect":
                    ConnectAsUser();
                    break;

                case "Disconnect":
                    send(new Disconnect(), this.stream);
                    enterForum();
                    this.Controller.Reset_Menu();
                    break;
                case "Exit":
                    break;
                default:
                    if (p.lengh() > 0)
                    {
                        try
                        {
                            int index = Int32.Parse(choice);
                            if (index > 0 && index <= p.lengh())
                            {
                                send(new View(index), this.stream);
                                this.Controller.LevelUP();
                            }
                            else
                            {
                                Console.WriteLine("\n*** you must choose from above *** - please try again\n");
                                viewPage(p);
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("\n*** you must choose from above *** - please try again\n");
                            viewPage(p);
                        }
                    }
                    else
                    {
                        Console.WriteLine("\n*** you must choose from above *** - please try again\n");
                        viewPage(p);
                    }
                    break;
            }


        }


        private void Enter_newPost()
        {
            Console.Write("enter Subject: ");
            String _subj = Console.ReadLine();
            Console.Write("enter Post: ");
            String _poste = Console.ReadLine();
            send(new CreatePost(_subj,_poste), this.stream);
        }

        private void Enter_Thread()
        {
            Console.Write("enter Subject: ");
            String _subjt = Console.ReadLine();
            Console.Write("enter Post: ");
            String _postet = Console.ReadLine();
            send(new CreateThread(_subjt, _postet), this.stream);
        }


        private void register()
        {
            Console.Write("name: ");
            String _name = Console.ReadLine();
            Console.Write("last name: ");
            String _lastname = Console.ReadLine();
            Console.Write("username: ");
            String _username = Console.ReadLine();
            Console.Write("password: ");
            String _password = Console.ReadLine();    ///need to be hide
            Console.Write("email: ");
            String _email = Console.ReadLine();
            send(new Register(_name, _lastname, _username, _password, _email), this.stream);
        }

        private void ConnectAsGuest()  ///
        {
            send(new Connect(), this.stream);
        }


        private void ConnectAsUser()  ///
        {
            this.tryConnect = true;
            Console.Write("username: ");
            String _username = Console.ReadLine();
            Console.Write("password: ");
            String _password = Console.ReadLine();    ///need to be hide
            send(new Connect(_username, _password), this.stream);
        }


        private void enterForum()  ///maybe need to be done as a page(request a page)
        {
            Console.WriteLine("");
            Console.WriteLine("1) Connect as a guest");
            Console.WriteLine("2) Connect as a user");
            Console.WriteLine("3) Register");
            String index = Console.ReadLine();  ///
            switch (index)
            {
                case "1":
                    ConnectAsGuest();
                    this.firstRun = false;
                    break;
                case "2":
                    ConnectAsUser();
                    break;
                case "3":
                    register();
                    break;
                default:
                    Console.WriteLine("\n*** you must choose from above *** - please try again\n");
                    enterForum();
                    break;
            }
        }




        private void send(Message msg, NetworkStream stream)
        {
           // Console.WriteLine("send from CLIENT to SERVER {0}", msg);  ///

            formatter.Serialize(stream, msg);
            //Logger.log(String.Format("<IP:{0}> SEND DATA: {1}", ((IPEndPoint)client.Client.RemoteEndPoint).Address, msg.GetType()));
        }
    }
}
